package main

import (
	"fmt"
	"net/http"

	"github.com/gin-gonic/gin"
)

// ============== 数据解析和绑定 ==============
// JSON ==> c.BindJSON(&xxx)	==> c.ShouldBindJSON(&xxx)
// Form ==> c.Bind(&xxx)
// URI  ==> c.BindUri(&xxx)
// XML  ==> c.BindXML(&xxx)
// YML  ==> c.BindYAML(&xxx)

type Login struct {
	// binding: "required" 修饰的字段是必须字段，若接收到的为空值，则报错
	// ****** 成员首字母必须大写 ******
	Username string `form:"username" json:"user" uri:"user" xml:"user" binding:"required"`
	Password string `form:"password" json:"password" uri:"password" xml:"password" binding:"required"`
}

func main() {
	// 1.创建路由
	// 默认使用了2个中间件Logger(), Recovery()
	r := gin.Default()

	// Json
	// curl http://localhost/loginJson -H 'content-type:application/json' -d "{\"user\":\"lxd\", \"password\":\"1234\"}" -X POST
	r.POST("/loginJson", loginJson)

	// curl http://localhost/loginJsonUseMap -H 'content-type:application/json' -d "{\"username\":\"lxd\", \"password\":\"1234\"}" -X POST
	r.POST("/loginJsonUseMap", loginJsonUseMap)

	// 1. curl http://localhost/loginForm -H 'content-type:application/x-www-form-urlencoded' -d "username=lxd&password=1234" -X POST
	// 2. 使用formbinding.html文件
	// POST的默认Content-Type:application/x-www-form-urlencoded
	r.POST("/loginForm", loginForm)

	// curl http://localhost/lxd/1234
	r.GET("/:user/:password", loginUri)

	r.Run(":80")
}

func loginJson(c *gin.Context) {
	login := Login{}
	// 将request的body中的数据，自动按照json格式解析到结构体
	if err := c.ShouldBindJSON(&login); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	fmt.Printf("login:%#v\n", login)
	// fmt.Println(c.PostForm("user"), c.PostForm("password"))

	// 判断用户名密码是否正确 数据库处理
	if login.Username != "lxd" || login.Password != "1234" {
		c.String(http.StatusBadRequest, "Authentication failed !!")
		return
	}

	c.JSON(http.StatusOK, gin.H{"msg": fmt.Sprintf("Welcome master %s", login.Username)})
}

func loginJsonUseMap(c *gin.Context) {
	login := make(map[string]interface{})

	if err := c.BindJSON(&login); err != nil {
		c.String(http.StatusBadRequest, "bindjson err:", err)
		return
	}

	fmt.Printf("login:%#v", login)

	// 判断用户名密码是否正确 数据库处理
	if login["username"] != "lxd" || login["password"] != "1234" {
		c.String(http.StatusBadRequest, "Authentication failed !!")
		return
	}

	c.JSON(http.StatusOK, gin.H{"msg": fmt.Sprintf("Welcome master %s", login["username"])})
}

func loginForm(c *gin.Context) {

	login := Login{}
	fmt.Printf("loginForm ==> header:%v\n", c.Request.Header)

	// // Bind() 默认解析并绑定form格式
	// // 根据请求头中的content-type自动推断
	// if err := c.Bind(&login); err != nil {
	// 	c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
	// 	return
	// }
	login.Username = c.PostForm("username")
	login.Password = c.PostForm("password")
	fmt.Printf("login:%v\n", login)

	// 判断用户名密码是否正确 数据库处理
	if login.Username != "lxd" || login.Password != "1234" {
		c.String(http.StatusBadRequest, "Authentication failed !!")
		return
	}

	file, err := c.FormFile("file")
	if err != nil {
		fmt.Println("formfile err:", err.Error())
		return
	} else {
		if err := c.SaveUploadedFile(file, file.Filename); err != nil {
			fmt.Println("SaveUploadedFile err:", err.Error())
			return
		}
	}

	c.YAML(http.StatusOK, gin.H{"msg": fmt.Sprintf("Welcome master %s", login.Username)})
}

func loginUri(c *gin.Context) {
	login := new(Login)

	if err := c.ShouldBindUri(login); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	fmt.Printf("login:%v\n", login)

	// 判断用户名密码是否正确 数据库处理
	if login.Username != "lxd" || login.Password != "1234" {
		c.String(http.StatusBadRequest, "Authentication failed !!")
		return
	}

	c.XML(http.StatusOK, gin.H{"msg": fmt.Sprintf("Welcome master %s", login.Username)})
}
